<?php

/**
 * Description of Token
 *
 * @author bonfiglio
 * @todo Commenter !!!
 */
class Token {

    private $properties = array();
    public $error = false;
    public $token = false;
    private static $salt = 'be6bc64c94bbc062bcebfb40b4f93304';

    public function __construct($token = false) {
        $this->token = $token;
        if ($this->token) {
            $this->setProperties();
            if (!$this->canBeUsed()) {
                $this->error = 'token expired';
            }
        }
    }

    public function generate($options = array()) {
        $this->token = $this->generateToken();

        $options['token'] = $this->token;
        $arguments = array(':token' => $this->token);
        $fields = array('token');

        if (isset($options['multiple_use'])) {
            $arguments[':multiple_use'] = (int) $options['multiple_use'];
            $fields[] = 'multiple_use';
        }

        if (isset($options['date_expired'])) {
            $arguments[':date_expired'] = $options['date_expired'];
            $fields[] = 'date_expired';
        }
        if (isset($options['data'])) {
            $arguments[':data'] = is_scalar($options['data']) ? $options['data'] : json_encode($options['data']);
            $fields[] = 'data';
        }
        $Database = Database::factory();
        $sql = '
            INSERT INTO `front`.`tokens`
            (' . implode(',', $fields) . ')
            VALUES
            (' . implode(',', array_keys($arguments)) . ');            
        ';
        $Database->Execute($sql, $arguments);
    }

    private function setProperties() {
        $Database = Database::factory();
        $Result = new Result($Database->Execute('SELECT * FROM tokens WHERE token = :token;', array(':token' => $this->token)));
        if ($Result->Count()) {
            $this->properties = $Result->Fetch();

            //Typage des données
            $this->properties['multiple_use'] = (boolean) $this->properties['multiple_use'];    // boolean, indique si ce token peut être utilisé plusieurs fois
            $this->properties['use_meter'] = (int) $this->properties['use_meter'];              // integer, compteur d'utilisation
            $this->properties['date_expired'] = (int) $this->properties['date_expired'];        // integer, date à laquelle le token expire
            $this->properties['data'] = json_decode($this->properties['data']);                 // json, data enregistrés (spécifique)
        } else {
            $this->error = "Ce token n'existe pas !";
        }
        return $this;
    }

    public function getData() {
        return $this->properties['data'];
    }

    private function isOutDated() {
        return $this->properties['date_expired'] < strtotime('now');
    }

    public function canBeUsed() {        
        return !$this->error && ( (!$this->properties['multiple_use'] && $this->properties['use_meter'] == 0) || $this->properties['multiple_use'] ) && !$this->isOutDated();
    }

    public function incrementUseMeter() {
        if ($this->token) {
            $Database = Database::factory();
            $Res = $Database->Execute('UPDATE tokens SET use_meter=use_meter+1 WHERE token = :token;', array(':token' => $this->token));
            if ($Res) {
                $this->properties['use_meter']++;
            }
        }
    }

    public static function generateToken() {
        return sha1(microtime() . self::$salt);
    }

}

?>
